package com.example.library_common.album.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import com.example.library_common.R;
import com.example.library_common.utils.PixUtils;

import org.jetbrains.annotations.NotNull;

import java.lang.ref.WeakReference;

public class RecordView extends View implements View.OnLongClickListener, View.OnClickListener {

    private static final int PROGRESS_INTERVAL = 100;

    private static final float MIN_SCALE = 0.8f;

    private static final float MAX_SCALE = 1.0f;

    public static final int ONLY_CAPTURE_IMG = 0;

    public static final int ONLY_CAPTURE_VIDEO = 1;

    public static final int ONLY_CAPTURE_ALL = 2;

    private final Paint fillPaint;

    private final Paint progressPaint;

    private int progressMaxValue;

    private final int radius;

    private final int progressWidth;

    private int progressValue = PixUtils.dp2px(3);

    private boolean isRecording;

    private boolean enableRecording = true;

    private long startRecordTime;

    private RectF arc = new RectF();

    private int mWidth;

    private int mHeight;

    private int captureType = ONLY_CAPTURE_IMG;

    private onRecordListener mListener;

    private RecordViewHandler handler;

    public void setEnableRecording(boolean enableRecording) {
        this.enableRecording = enableRecording;
        if (!enableRecording) {
            setOnClickListener(this);
            setOnLongClickListener(null);
        } else {
            setClickEnable();
        }
    }

    public RecordView(Context context) {
        this(context, null);
    }

    public RecordView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RecordView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);


        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RecordView);

        radius = typedArray.getDimensionPixelOffset(R.styleable.RecordView_radius, 0);

        progressWidth = typedArray.getDimensionPixelOffset(R.styleable.RecordView_progress_width, progressValue);

        int progressColor = typedArray.getColor(R.styleable.RecordView_progress_color, Color.RED);

        int fillColor = typedArray.getColor(R.styleable.RecordView_fill_color, Color.WHITE);

        int maxDuration = typedArray.getInteger(R.styleable.RecordView_duration, 10);

        captureType = typedArray.getInt(R.styleable.RecordView_capture_action, captureType);

        setMaxDuration(maxDuration);

        typedArray.recycle();

        fillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        fillPaint.setColor(fillColor);
        fillPaint.setStyle(Paint.Style.FILL);

        progressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        progressPaint.setColor(progressColor);
        progressPaint.setStyle(Paint.Style.STROKE);
        progressPaint.setStrokeWidth(progressWidth);

        handler = new RecordViewHandler(this);

        setClickEnable();


    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = MeasureSpec.getSize(widthMeasureSpec);
        mHeight = MeasureSpec.getSize(heightMeasureSpec);
    }

    private void finishRecord() {
        if (mListener != null) {
            mListener.onFinish();
        }

    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
//                isRecording = true;

                startRecordTime = System.currentTimeMillis();
                handler.sendEmptyMessage(0);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:

                long now = System.currentTimeMillis();
                if (now - startRecordTime > ViewConfiguration.getLongPressTimeout()) {
                    finishRecord();
                }
                handler.removeCallbacksAndMessages(null);
                isRecording = false;

                startRecordTime = 0;
                progressValue = 0;
                postInvalidate();
                break;
        }


        return super.onTouchEvent(event);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        float cx = mWidth >> 1;
        float cy = mHeight >> 1;
        float scale = isRecording ? MAX_SCALE : MIN_SCALE;
        float realRadius = Math.min(radius, (Math.min(mWidth, mHeight) >> 1)) * scale;

        canvas.drawCircle(cx, cy, realRadius, fillPaint);

        float offset = progressWidth >> 1;

        boolean isDrawArc = isRecording && isCaptureForVideo() && enableRecording;

        if (isDrawArc) {

            arc.left = cx - realRadius + offset;
            arc.top = cy - realRadius + offset;
            arc.right = cx + realRadius - offset;
            arc.bottom = cy + realRadius - offset;

            float sweepAngle = (progressValue * 1.0f / progressMaxValue) * 360;

            canvas.drawArc(arc, -90, sweepAngle, false, progressPaint);
        }
    }

    public void setMaxDuration(int maxDuration) {
        this.progressMaxValue = maxDuration * 1000 / PROGRESS_INTERVAL;
    }

    public void setOnRecordListener(onRecordListener listener) {

        mListener = listener;
    }

    public void setCaptureType(int captureType) {
        Log.d("setCaptureType", "setCaptureType: " + captureType);
        if (captureType == ONLY_CAPTURE_ALL
                || captureType == ONLY_CAPTURE_VIDEO
                || captureType == ONLY_CAPTURE_IMG) {
            this.captureType = captureType;
        }

        setClickEnable();
    }

    private void setClickEnable() {
        if (captureType == ONLY_CAPTURE_IMG) {

            setOnClickListener(this);
            setOnLongClickListener(null);
        } else if (captureType == ONLY_CAPTURE_VIDEO) {
            setOnClickListener(null);
            setOnLongClickListener(this);
        } else {
            setOnClickListener(this);
            setOnLongClickListener(this);
        }
    }

    @Override
    public boolean onLongClick(View v) {
        if (mListener != null && isCaptureForVideo()) {
            isRecording = true;
            mListener.onLongClick();
        }
        return true;
    }

    private boolean isCaptureForVideo() {
        return captureType == ONLY_CAPTURE_ALL || captureType == ONLY_CAPTURE_VIDEO;
    }

    private boolean isCaptureForImg() {
        return captureType == ONLY_CAPTURE_ALL || captureType == ONLY_CAPTURE_IMG;
    }

    @Override
    public void onClick(View v) {
        if (mListener != null && isCaptureForImg() && enableRecording) {
            mListener.onClick();
        } else {
            if (mListener != null) {
                mListener.onError();
            }
        }
    }

    public interface onRecordListener {
        void onClick();

        void onLongClick();

        void onFinish();

        void onError();
    }

    static class RecordViewHandler extends android.os.Handler {
        private WeakReference<RecordView> weakReference;

        public RecordViewHandler(RecordView controlView) {
            weakReference = new WeakReference<>(controlView);
        }

        @Override
        public void handleMessage(@NotNull Message msg) {
            super.handleMessage(msg);
            if (weakReference == null || weakReference.get() == null) return;
            final RecordView videoControlView = weakReference.get();
            videoControlView.progressValue++;
            videoControlView.postInvalidate();
            if (videoControlView.progressValue <= videoControlView.progressMaxValue) {
                sendEmptyMessageDelayed(0, PROGRESS_INTERVAL);
            } else {
                videoControlView.finishRecord();
            }
        }
    }
}